﻿var Scrumboard = {};

function scrumboard(id, backlogName, tfsLocator) {

    Scrumboard = this;

    this.m_id = id;
    this.m_backlogName = backlogName;
    this.m_tfsLocator = tfsLocator;
    this.m_lastWorkitem = 0;

    this.m_applicationPath = '/';
    this.m_scrumboardServiceGetPlanning = 'Services/ScrumboardService.asmx/GetPlanning';
    this.m_scrumboardServiceUpdatePriority = 'Services/ScrumboardService.asmx/UpdatePriority';
    this.m_scrumboardServiceUpdatePlanning = 'Services/ScrumboardService.asmx/UpdatePlanning';

    // object initialization
    this.init = function () {
        var _this = this;

        var posIndex = CommonUrls.Default.toLowerCase().indexOf('index.aspx');
        if (posIndex >= 0) {
            this.m_applicationPath = CommonUrls.Default.substr(0, posIndex);
        }
        if (this.m_applicationPath == '') {
            this.m_applicationPath = '/';
        }
    }

    // page initialization
    this.initPage = function () {
        $('#ctl00_split').hide();
        $('#scrumboard-middle').appendTo('#ctl00_pnlMiddle');
        $('#ctl00_pnlMiddle').css('overflow', 'auto');

        this.initBacklogs();

        this.setupResize();
    }
    // planning-page initialization
    this.initPlanningPage = function (model) {
        this.initPage();

        this.showPlanning(model);
    }
    // TODO: tasks-page initialization
    this.initTasksPage = function () {
        this.initPage();
    }

    // backlog(group)s initialization
    this.initBacklogs = function () {
        // backlog-group-content list items: hover showes colored bar
        $('.backlog-group-content ul li:not(.more-less)').hover(
            function () { $(this).addClass('hover'); },
            function () { $(this).removeClass('hover'); }
        );

        // backlog-group: click on caption collapses/expands backlog-group-content
        $('.history-backlog-group .backlog-group-caption').click(this.toggleBacklogGroupContent);
        $('.current-backlog-group .backlog-group-caption').click(this.toggleBacklogGroupContent);
        $('.future-backlog-group .backlog-group-caption').click(this.toggleBacklogGroupContent);

        // show-more/-less: collapse/expand
        $('.backlog-group-content li.show-more').click(this.showMoreBacklogGroupContent);
        $('.backlog-group-content li.show-less').click(this.showLessBacklogGroupContent);

        // click blacklog: open backlog
        $('.backlog-group-content li:not(.more-less)').click(this.openBacklog);
    }

    // backlog(group)s functions
    this.toggleBacklogGroupContent = function () {
        $(this).next().toggle();

        $(this).find('.backlog-group-icon').toggleClass('icon-collapsed');
        $(this).find('.backlog-group-icon').toggleClass('icon-expanded');

        Scrumboard.resizeSplitter();
    }
    this.showMoreBacklogGroupContent = function () {
        $(this).hide();
        $(this).nextAll().show();

        Scrumboard.resizeSplitter();
    }
    this.showLessBacklogGroupContent = function () {
        $(this).hide();
        $(this).parent().children('.more-backlog').hide();
        $(this).parent().children('.show-more').show();

        Scrumboard.resizeSplitter();
    }
    this.openBacklog = function () {
        Scrumboard.openPlanning($(this).text());
    }

    // toolbar functions
    this.refreshPlanning = function () {
        this.openPlanning(this.m_backlogName);
    }

    // resize functions
    this.setupResize = function () {
        $('#splitHandle').click(this.toggleSplitter);

        this.resizeScrumboard();
        $(window).resize(this.resizeScrumboard);
        $('#ctl00_pnlMiddle').scroll(this.resizeScrumboard);
    }
    this.resizeScrumboard = function () {
        var windowHeight = $(window).height();
        var headerHeight = $('#ctl00_pnlHead').height();
        var containerHeight = windowHeight - headerHeight;
        var leftHeight = $('#leftSide').height();
        var fillerHeight = $('#leftSide-filler').height();
        var rightHeight = $('#scrumboard-container').height();
        var scrollTop = $('#ctl00_pnlMiddle').scrollTop();

        var windowWidth = $(window).width();
        var containerWidth = $('#scrumboard-middle').width();

        leftHeight -= fillerHeight;

        var splitterHeight = 0;
        if (leftHeight > splitterHeight) {
            splitterHeight = leftHeight;
        }
        if (rightHeight > splitterHeight) {
            splitterHeight = rightHeight;
        }
        if (containerHeight > splitterHeight) {
            splitterHeight = containerHeight;
        }
        if (splitterHeight > 20) {
            splitterHeight -= 20;
        }
        if (splitterHeight < leftHeight) {
            splitterHeight = leftHeight;
        }

        var splitterPosition = ((windowHeight - headerHeight) / 2) + scrollTop - 25;

        $('#splitHandle').height(splitterHeight);
        $('#leftSide-filler').height(splitterHeight - leftHeight);

        //$('#planning-caption span').html(containerHeight + ' - ' + leftHeight + ' - ' + rightHeight + ' - (' + splitterHeight + '); [' + windowWidth + ', ' + containerWidth + ']');
    }
    // TODO: page resizing
    //    this.resizeContainer = function () {

    //        var windowWidth = $(window).width();
    //        var containerLeft = $('#scrumboard-container').position().left;
    //        var containerWidth = $('#scrumboard-container').width();

    //        if (containerWidth < 400) {
    //            $('#scrumboard-container').width(400);
    //            $('#scrumboard-container').css('min-width', 400);
    //            $('#scrumboard-container').css('overflow', 'auto');
    //        }

    //        $('.title').width(100);
    //        $('.title').css('min-width', 100);

    //        var html = windowWidth + ' - ' + containerLeft + ' - ' + containerWidth;
    //        $('#ctl00_c_workItems_backlogName').html(html);
    //    }

    this.toggleSplitter = function () {
        $('#leftSide').toggle();
    }

    // show planning from a backlog
    this.showPlanning = function (model) {

        // remember the backlog-name for the refresh
        this.m_backlogName = model.BacklogName;

        // set the query-results values to a '0' string or nothing will show
        if (model.QueryResults.TotalWorkItems == 0) {
            model.QueryResults.TotalWorkItems = '0';
        }
        if (model.QueryResults.TotalStoryPoints == 0) {
            model.QueryResults.TotalStoryPoints = '0';
        }

        // TODO: find a better way to link workitem-types to images
        $(model.WorkItems).each(function (index, item) {
            var imageName = '';
            switch (item.WorkItemType) {
                case 'Product Backlog Item':
                case 'Requirement':
                case 'User Story':
                    imageName = 'Requirement.gif';
                    break;

                default:
                    imageName = item.WorkItemType + '.gif';
                    break;
            }
            item.WorkItemTypeImageUrl = Scrumboard.m_applicationPath + 'Resources/Images/WorkItems/' + imageName;
        });

        // show the backlog-name
        $('#planning-caption span').html(model.BacklogName);

        // render the query-results in the model to html & replace the query-results on the page
        var htmlInfo = $("#infoTemplate").render(model.QueryResults);
        $("#planning-workitems-info").html(htmlInfo);

        // render the workitems in the model to html & replace the planning data on the page
        var htmlWorkItems = $("#workitemTemplate").render(model.WorkItems);
        $("#planning-workitems tbody").empty().html(htmlWorkItems);

        this.updatePlanningBreadCrumb();

        this.initPlanning();
    }

    // initialize planning
    this.initPlanning = function () {
        // hover over work-item: highlight the work-item
        $('#planning-workitems tr').hover(
            function () { $(this).addClass('planning-workitem-hover'); },
            function () { $(this).removeClass('planning-workitem-hover'); }
        );

        // double-click work-item: open work-item dialog
        $('#planning-workitems tr').dblclick(
            function () { DocumentService.showWorkItem($(this).attr('workItemId'), this.m_tfsLocator); }
        );

        // drop work-item on backlog: move work-item to backlog
        $('#planning-workitems tr').bind('selectstart', function () { return false; });
        $("#planning-workitems tbody").sortable({
            placeholder: 'planning-workitem-placeholder',
            items: 'tr',
            zIndex: 2000,
            cursor: 'default',
            start: function (event, ui) {
                ui.placeholder.html('<td colspan=7 />');
            },
            stop: function (event, ui) {
                $(ui.item).css('z-index', 1000);
                $('#planning-workitems tr').removeClass('planning-workitem-hover');
            },
            update: this.updatePriority
        }).disableSelection();

        // drop work-item on backlog: move work-item to backlog
        $("#backlogs-container li").droppable({
            tolerance: 'pointer',
            hoverClass: 'hover',
            drop: this.updatePlanning
        });
    }

    this.createPlanningUrl = function (params) {
        return DocumentService.createUrl(this.m_applicationPath + this.m_pagesFolder + this.m_planningPage, params, this.m_tfsLocator);
    }

    this.updatePlanningBreadCrumb = function () {
        if (PageToolbar && PageToolbar.updateBreadCrumb) {
            var breadCrumb = [];

            breadCrumb.push({ text: PageResources.Home, url: DocumentService.createUrl(CommonUrls.Default) });
            breadCrumb.push({ text: this.m_planningTitle, url: this.createPlanningUrl(null) });
            if (this.m_backlogName != '') {
                breadCrumb.push({ text: this.m_backlogName, url: 'javascript:Scrumboard.openPlanning("' + this.m_backlogName + '")' });
            }

            PageToolbar.updateBreadCrumb(breadCrumb);
        }
    }

    // open the planning for a specific backlog
    this.openPlanning = function (backlogName) {
        PopupManager.hide();

        var planningUrl = DocumentService.createUrl(this.m_applicationPath + this.m_scrumboardServiceGetPlanning, null, this.m_tfsLocator);

        // TODO: block UI while retrieving and rendering the planning
        //        $.blockUI({
        //            message: '<img src="/tfs/web/Resources/Images/big-progress.gif" />',
        //            css: {
        //                border: 'none',
        //                backgroundColor: '#fff',
        //                opacity: 1.0,
        //                width: '68px',
        //                height: '68px',
        //                top: '45%',
        //                left: '45%'
        //            },
        //            overlayCSS: {
        //                backgroundColor: '#000',
        //                opacity: 0.0
        //            }
        //        });

        $.ajax({
            type: "POST",
            dataType: 'json',
            contentType: 'application/json; charset=UTF-8',
            async: false,
            url: planningUrl,
            data: "{backlogName:'" + backlogName + "'}",
            success: function (json) {
                Scrumboard.showPlanning(json.d);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                //alert('An error occured while loading the requested backlog');  
            },
            complete: function () {
                //$.unblockUI();
            }
        });
    }

    this.updatePriority = function (event, ui) {
        if (!$(ui.item).hasClass('deleted')) {                                      // a deleted item should not be sortable/draggable
            var id = $(ui.item).attr('workItemId');

            // if update-planning was called for this work-item; skip update-priority
            if (Scrumboard.m_lastWorkitem == id) {
                Scrumboard.m_lastWorkitem = 0;
                return;
            }

            var idPrev = $(ui.item).prev(':not(.deleted)').attr('workItemId');      // find previous workitem-id, but skip the deleted
            var idNext = $(ui.item).next(':not(.deleted)').attr('workItemId');      // find next workitem-id, but skip the deleted

            idPrev = idPrev != undefined ? idPrev : null;
            idNext = idNext != undefined ? idNext : null;

            var updatePriorityUrl = DocumentService.createUrl(Scrumboard.m_applicationPath + Scrumboard.m_scrumboardServiceUpdatePriority, null, Scrumboard.m_tfsLocator);

            // update the priority of the moved item; and any other items as needed to apply the new priority
            $.ajax({
                type: "POST",
                dataType: 'json',
                contentType: 'application/json; charset=UTF-8',
                async: false,
                url: updatePriorityUrl,
                data: "{backlogName:'" + Scrumboard.m_backlogName + "', id:" + id + ", previousId:" + idPrev + ", nextId:" + idNext + "}",
                success: function (json) {
                    if (json.d != null) {
                        // refresh the planning-page (workitems & query-results), to reflect the changes
                        Scrumboard.showPlanning(json.d);
                    }
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    //alert('An error occured while updating the priority of the requested workitem');  
                }
            });

            //showUpdatePriorityAlert(id, idPrev, idNext);
        }
    }

    this.updatePlanning = function (event, ui) {
        var id = $(ui.draggable).attr('workItemId');
        var backlogName = $(this).text();

        // remember this work-item; skip it if update-priority is called as well
        Scrumboard.m_lastWorkitem = id;

        var updatePlanningUrl = DocumentService.createUrl(Scrumboard.m_applicationPath + Scrumboard.m_scrumboardServiceUpdatePlanning, null, Scrumboard.m_tfsLocator);

        // update the planning of the moved item
        $.ajax({
            type: "POST",
            dataType: 'json',
            contentType: 'application/json; charset=UTF-8',
            async: false,
            url: updatePlanningUrl,
            data: "{backlogName:'" + Scrumboard.m_backlogName + "', id:" + id + ", updateBacklogName:'" + backlogName + "'}",
            success: function (json) {
                // refresh the planning-page (workitems & query-results), to reflect the changes
                // NOTE: backlogs are static on the page & no statistics are currently shown; so no need to refresh the backlogs
                if (json.d != null) {
                    Scrumboard.showPlanning(json.d);
                }
            },
            error: function (jqXHR, textStatus, errorThrown) {
                //alert('An error occured while updating the priority of the requested workitem');  
            }
        });

        //showUpdatePlanningAlert(id, backlogName);
    }

    // debug alert helper functions
    function showUpdatePriorityAlert(id, idPrev, idNext) {
        if (idPrev != undefined && idNext != undefined) {
            showAlert("drop '" + id + "' between '" + idPrev + "' and '" + idNext + "'");
        }
        else if (idPrev == undefined && idNext != undefined) {
            showAlert("drop '" + id + "' before '" + idNext + "'");
        }
        else if (idPrev != undefined && idNext == undefined) {
            showAlert("drop '" + id + "' after '" + idPrev + "'");
        }
        else {
            showAlert('invalid drop');
        }
    }
    function showUpdatePlanningAlert(id, backlogName) {
        showAlert('moved item ' + id + ' to ' + backlogName);
    }
    function showAlert(message) {
        alert(message);
    }
}
